﻿import flash.geom.Matrix;
import My3D.Face;
import My3D.Screen;

dynamic class My3D.Testure {
	//--------------------------------------------------------------------------------------
	//																					static
	public static var SmoothBMP:Boolean = true;
	//--------------------------------------------------------------------------------------
	//																					private
	private var $screen:Screen;
	
	//--------------------------------------------------------------------------------------
	//																					public
	public function get rootScreen():Screen {
		return this.$screen;
	}
	
	
	//--------------------------------------------------------------------------------------
	//																					function 
	public function Testure(screen:Screen) {
		initsay();
		if (screen == undefined) {
			_say.wsay("not set screen.");
			return;
		}
		this.$screen = screen;
		initvars();
		_say.msay("inited!");
	}
	private function initvars() {
		
	}
	/* 使用属性参数将大大增加运算时间！
	public function testureFace(f:Face) {
		if (f.TestureInfo.testureOnFace) {
			if (f.RootMc != undefined) {
				if (f.TestureInfo.bitmapMaterial == undefined || !f.TestureInfo.bitmapMaterial.Loaded) {
					renderWithDraw(f.RootMc, f);
				}else {
					renderWithBitmap(f.RootMc, f);
				}
			}else {
				_say.esay("can't render for null rootMc in face["+f.ID+"]");
			}
		}else {
			if ($screen.RootMc != undefined) {
				if (f.TestureInfo.bitmapMaterial == undefined || !f.TestureInfo.bitmapMaterial.Loaded) {
					renderWithDraw($screen.RootMc, f);
				}else {
					renderWithBitmap($screen.RootMc, f);
				}
			}else {
				_say.esay("can't render for null rootMc in screen");
			}
		}
	}
	*/
	/**
	 * 给一个面贴图，使用非属性方式
	 * @param	f 面
	 */
	public function testureFace(f:Face) {
		if (!f.visible) {
			return;
		}
		if (checkCW(f)) {
			return;
		}
		if (f.$testureInfo.testureOnFace) {
			if (f.$rootmc != undefined) {
				f.$rootmc.clear();
				if (f.$testureInfo.bitmapMaterial == undefined || !f.$testureInfo.bitmapMaterial.Loaded) {
					renderWithDraw(f.$rootmc, f);
				}else {
					renderWithBitmap(f.$rootmc, f);
				}
			}else {
				_say.esay("can't render for null rootMc in face["+f.ID+"]");
			}
		}else {
			
			if ($screen.RootMc != undefined) {
				if (f.$testureInfo.bitmapMaterial == undefined || !f.$testureInfo.bitmapMaterial.Loaded) {
					renderWithDraw($screen.RootMc, f);
				}else {
					renderWithBitmap($screen.RootMc, f);
				}
			}else {
				_say.esay("can't render for null rootMc in screen");
			}
		}
	}
	
	private function checkCW(face:Face) {
			if (!this.$screen.testureSingleFace) {
				return false;
			}
			var xx0:Number = face.$pointA.X;
			var yy0:Number = face.$pointA.Y;
			var xx1:Number = face.$pointB.X;
			var yy1:Number = face.$pointB.Y;
			var xx2:Number = face.$pointC.X;
			var yy2:Number = face.$pointC.Y;
		
		var fun:Function = Math2.lineEquation( { x0:xx0, y0:yy0, x1:xx2, y1:yy2 }, false);
		var my:Number = fun(xx1);
		if (yy1 > my) {
			if(xx2>xx0){
				//逆时针
				return false;
			}else {
				//顺时针
				return true;
			}
		}else {
			if(xx2<xx0){
				//逆时针
				return false;
			}else {
				//顺时针
				return true;
			}
		}
	}
	
	private function renderWithBitmap(mc:MovieClip, f:Face) {
		
		
		var m:Matrix = new Matrix();
		
		var off0:Number = f.$testureInfo.UVPointOffset;
		var off1:Number = (f.$testureInfo.UVPointOffset + 1) % 3;
		var off2:Number = (f.$testureInfo.UVPointOffset + 2) % 3;
		
		
		var arr1:Array = [f.$pointA, f.$pointB, f.$pointC];
		var arr2:Array = [f.$testureInfo.UVpointA, f.$testureInfo.UVpointB, f.$testureInfo.UVpointC];
		
		//var w2:Number = f.$pointC.U - f.$pointB.U;
		var w2:Number = arr2[off2].U - arr2[off1].U;
		//var h2:Number = f.$pointB.V - f.$pointA.V;
		var h2:Number = arr2[off1].V - arr2[off0].V;
		
		if (w2 == 0) {
			return;
		}
		//trace(f.ID)
		if (h2 == 0) {
			return;
		}
		
		//var w1:Number = f.$pointC.X - f.$pointB.X;
		//var h1:Number = f.$pointB.Y - f.$pointA.Y;
		
		var w1:Number = arr1[off2].X - arr1[off1].X;
		var h1:Number = arr1[off1].Y - arr1[off0].Y;
		
		var bw:Number = (w1 / w2);
		var bh:Number = (h1 / h2);
		
		//Debug.traceAll( w1, bw, h1, bh);
		//Debug.traceAll( f.PointA, f.PointB,f.PointC);
		
		
		//var h1w:Number = f.$pointB.X - f.$pointA.X;
		//var h2w:Number = f.$pointB.U - f.$pointA.U;
		//var w1h:Number = f.$pointC.Y - f.$pointB.Y;
		//var w2h:Number = f.$pointC.V - f.$pointB.V;
		
		var h1w:Number = arr1[off1].X - arr1[off0].X;
		var h2w:Number = arr2[off1].U - arr2[off0].U;
		var w1h:Number = arr1[off2].Y - arr1[off1].Y;
		var w2h:Number = arr2[off2].V - arr2[off1].V;
		
		//var WL:Number = scrPointC.y - scrPointB.y - f.PointC.V + f.PointB.V;
		//var HL:Number = scrPointB.x - scrPointA.x - f.PointB.U + f.PointA.U;
		
		m.a = bw;
		var b:Number =(w1h - w2h) / w2;
		var c:Number=(h1w - h2w) / h2;
		m.b = b;
		m.c = c;
				
		//var u:Number = f.$pointB.U * bw + f.$pointB.V * c;
		//var v:Number = f.$pointB.V * bh + f.$pointB.U * b;
		
		var u:Number = arr2[off1].U * bw + arr2[off1].V * c;
		var v:Number = arr2[off1].V * bh + arr2[off1].U * b;
		m.d = bh;
		//m.tx = f.$pointB.X - u;
		//m.ty = f.$pointB.Y - v;
		m.tx = arr1[off1].X - u;
		m.ty = arr1[off1].Y - v;
		/*--------*/
		
		mc.beginBitmapFill(f.$testureInfo.bitmapMaterial.$bmp, m, true, SmoothBMP);
		mc.lineStyle(f.$testureInfo.lineThickness, f.$testureInfo.lineColor, f.$testureInfo.lineAlpha);
		drawT(mc, f.$pointA.X,f.$pointA.Y, f.$pointB.X,f.$pointB.Y, f.$pointC.X,f.$pointC.Y);
		mc.endFill();
	}
	private function renderWithDraw(mc:MovieClip, f:Face) {
		mc.beginFill(f.$testureInfo.backGroundColor, f.$testureInfo.backGroundAlpha);
		mc.lineStyle(f.$testureInfo.lineThickness, f.$testureInfo.lineColor, f.$testureInfo.lineAlpha);
		drawT(mc, f.$pointA.X,f.$pointA.Y, f.$pointB.X,f.$pointB.Y, f.$pointC.X,f.$pointC.Y);
		mc.endFill();
	}
	
	private static function drawT(mc, p1x:Number,p1y:Number, p2x:Number,p2y:Number, p3x:Number,p3y:Number) {
		//trace(arguments);
		
		mc.moveTo(p1x, p1y);
		mc.lineTo(p2x, p2y);
		mc.lineTo(p3x, p3y);
		mc.lineTo(p1x, p1y);
		/*
		mc.moveTo(-Stage.width, -Stage.width);
		mc.lineTo(Stage.width,-Stage.width);
		mc.lineTo(Stage.width, Stage.height);
		mc.lineTo(-Stage.width, Stage.height);
		*/
	}
	////////////////////////////////////////////////////////////////      output
	private var _say:Say;
	private function initsay() {
		_say = new Say("Testure");
		_say.addListener(this);
		this[Say.M_SAY] = this.sayfun;
	}
	private function sayfun(o) {
		trace(o);
	}
}